<template>
  <div
    class="segmented-select bg-[rgb(var(--v-theme-background),0.5)] relative flex text-title text-sm items-center justify-between box-border text-center"
  >
    <div class="flex w-full bg-transparent z-10" ref="segmentedSelectRef">
      <div
        v-for="(item, index) in items"
        :key="index"
        @click="onSelect(index)"
        class="cursor-pointer text-sm px-4 py-2 segmented-item select-none"
      >
        {{ isSegmentedSelectOption(item) ? item.label : item }}
      </div>
    </div>
    <div class="absolute thumb"></div>
  </div>
</template>
<script setup lang="ts" generic="T">
import { withDefaults, defineEmits, toRefs, watchEffect } from "vue";
import { useVModels, useElementBounding } from "@vueuse/core";
import { computed } from "vue";
import { SegmentedSelectOption } from "./type";
import { isSegmentedSelectOption } from "./utils";
import { ref, useTemplateRef } from "vue";
const props = withDefaults(
  defineProps<{
    items: string[] | SegmentedSelectOption<T>[];
    modelValue: T | number;
    rounded?: number | string;
    padding?: number;
    thumbColor?: string;
  }>(),
  {
    rounded: `9999px`,
    padding: 4,
    thumbColor: "rgb(var(--v-theme-primary), 0.8)",
  }
);
const emit = defineEmits(["update:modelValue", "change"]);
const segmentedSelectRef = useTemplateRef<HTMLDivElement>("segmentedSelectRef");
const childNodesRef = ref<HTMLDivElement[]>([]);
const {
  left: segmentedSelectLeft,
  width: segmentedSelectWidth,
  height: segmentedSelectHeight,
} = useElementBounding(segmentedSelectRef);

const { items, padding } = toRefs(props);
const { modelValue } = useVModels(props, emit);

const currentIndex = computed(() => {
  if (items.value.length > 0 && isSegmentedSelectOption(items.value[0])) {
    return items.value.findIndex((item: SegmentedSelectOption<T>) => item.value === modelValue.value) as number;
  }
  return modelValue.value as number;
});
const thumbLeft = computed(() => {
  const reduceLeft = childNodesRef.value.reduce((prev, cur, index) => {
    if (index < currentIndex.value) {
      return prev + (cur.getBoundingClientRect().width || 0);
    }
    return prev;
  }, 0);
  console.log(reduceLeft);
  if (reduceLeft) {
    return `${reduceLeft + padding.value}px`;
  }
  return `${padding.value}px`;
});

const thumbWidth = computed(() => {
  const width = childNodesRef.value?.[currentIndex.value]?.getBoundingClientRect()?.width;
  if (width) {
    return `${width}px`;
  }
  return `${segmentedSelectWidth.value / items.value.length}px`;
});

const thumbTop = computed(() => {
  return `${padding.value}px`;
});

const thumbHeight = computed(() => {
  return `${segmentedSelectHeight.value}px`;
});

const thumbRounded = computed(() => {
  if (typeof props.rounded === "number") {
    return `${props.rounded}px`;
  }
  return props.rounded;
});

const segmentedPadding = computed(() => {
  return `${padding.value}px`;
});

function onSelect(index: number) {
  const isSeg = isSegmentedSelectOption(items.value[index]);
  modelValue.value = isSeg ? items.value[index].value : index;
  emit("change", index, isSeg ? items.value[index].value : index);
}

watchEffect(() => {
  childNodesRef.value = Array.from(segmentedSelectRef.value?.querySelectorAll(".segmented-item") || []);
});
</script>
<style scoped lang="scss">
.segmented-select {
  padding: v-bind(segmentedPadding);
  border-radius: v-bind(thumbRounded);
}
.thumb {
  width: v-bind(thumbWidth);
  left: 0px;
  top: v-bind(thumbTop);
  height: v-bind(thumbHeight);
  transition: transform 0.3s linear;
  background-color: v-bind(thumbColor);
  border-radius: v-bind(thumbRounded);
  transform: translateX(v-bind(thumbLeft));
}
</style>
